#include "NoSpread.h"

NoSpread g_pNoSpread;

CBaseCombatWeapon* NoSpread::GetBaseCombatWeapon(void* pEntity)
{
	CBaseHandle hActiveWeapon = *reinterpret_cast<CBaseHandle*>((DWORD)pEntity + Offsets::m_hActiveWeapon); 
	return (CBaseCombatWeapon*)(g_pInterfaces.g_pEntList->GetClientEntityFromHandle(hActiveWeapon)); 
}

float RandomFloat(float min, float max)
{
 	typedef float (* RandomFloat_t)(float,float);
 	static RandomFloat_t m_RandomFloat = (RandomFloat_t)GetProcAddress(GetModuleHandle(L"vstdlib.dll"), "RandomFloat");
	return m_RandomFloat(min,max);
}

void RandomSeed(UINT seed)
{
 	typedef void (* RandomSeed_t)(UINT);
 	static RandomSeed_t m_RandomSeed = (RandomSeed_t)GetProcAddress(GetModuleHandle(L"vstdlib.dll"), "RandomSeed");
 	m_RandomSeed(seed);
	return;
}

void NoSpread::GetSpreadXY(UINT seed, SD_Tools::Vector & qAngle)
{
	seed = seed & 255;
	seed++;
	RandomSeed(seed);

	Entity* pLocal = g_pInterfaces.g_pEntList->GetClientEntity(g_pInterfaces.g_pEngine->GetLocalPlayer());
	if(!pLocal)
		return;

	CBaseCombatWeapon* pWeapon = GetBaseCombatWeapon(pLocal->GetBaseEntity());
	if (!pWeapon)
		return;

	pWeapon->UpdateAccuracyPenalty();

	float Spread[2];
	Spread[0] = pWeapon->GetSpread();
	Spread[1] = pWeapon->GetInaccuracy();

	float Randoms[4];
	Randoms[0] = RandomFloat(0.0f, 2.0f * SD_Tools::SD_PI_F);
	Randoms[1] = RandomFloat(0.0f, Spread[0]);
	Randoms[2] = RandomFloat(0.0f, 2.0f * SD_Tools::SD_PI_F);
	Randoms[3] = RandomFloat(0.0f, Spread[1]);

	qAngle.x = (cos(Randoms[0]) * Randoms[1]) + (cos(Randoms[2]) * Randoms[3]);
	qAngle.y = (sin(Randoms[0]) * Randoms[1]) + (sin(Randoms[2]) * Randoms[3]);
}

void NoSpread::GetSpreadFix(UINT Seed, SD_Tools::Angle &vIn, SD_Tools::Angle &vOut)
{
	SD_Tools::Vector vF,vR,vU,vDir;
	SD_Tools::Vector View,Spread;
	SD_Tools::Angle Dest;
	
	SD_Tools::MathHelper::AngleToVectors(vIn,&vF,&vR,&vU);
	
	GetSpreadXY(Seed,Spread);

	vDir.x = vF.x + Spread.x * vR.x + Spread.y * vU.x;
	View.x = 8192.0f * vDir.x;
	vDir.y = vF.y + Spread.x * vR.y + Spread.y * vU.y;
	View.y = 8192.0f * vDir.y;
	vDir.z = vF.z + Spread.x * vR.z + Spread.y * vU.z;
	View.z = 8192.0f * vDir.z;

	View.ToAngles(&Dest);
	
	vOut.x = vIn.x - Dest.x;
	vOut.y = vIn.y - Dest.y;
	vOut.z = 0;
}

void NoSpread::ApplyNoRecoil(CUserCmd* cmd)
{
	Entity* pMe = g_pInterfaces.g_pEntList->GetClientEntity(g_pInterfaces.g_pEngine->GetLocalPlayer());
	SD_Tools::Vector* punch = pMe->getRecoilVec();
	cmd->viewangles.Pitch -= punch->x * 2;
	cmd->viewangles.Yaw -= punch->y * 2;
	cmd->viewangles.Roll = 0.f;
}